﻿using System;
using System.Collections.Generic;
using ExcelMerge;
using OfficeOpenXml;

public class CellDiffItem : IDiffItem<CellDiffItem>
{
    private readonly bool _lineFeed;
    private readonly int _hash = 0;

    public int Row { get; } = 0;
    public int Col { get; } = 0;
    public string Value { get; }
    public PatchState PatchedState { get; set; }
    private readonly ExcelRange _originCell;

    public CellDiffItem(int row,int col)
    {
        Row = row;
        Col = col;
        Value = string.Empty;
        _lineFeed = true;
        _hash = HashCode.Combine(true.GetHashCode());
    }
    
    public CellDiffItem(int row,int col,ExcelRange cell)
    {
        if (cell.Rows != 1 || cell.Columns != 1)
        {
            throw new Exception($"Row={row},Col={col} 目标单元格不是单个单元格,请取消合并后再处理");
        }
        Row = row;
        Col = col;
        Value = cell.Value?.ToString() ?? string.Empty;
        _lineFeed = false;
        _originCell = cell;
        _hash = CalculateHashCode();
    }

    public void ToCell(ExcelRange cell)
    {
        //cell.Value = Value;
        _originCell.Copy(cell);
    }

    public bool IsControl()
    {
        return IsLineFeed();
    }

    public bool IsLineFeed()
    {
        return _lineFeed;
    }

    public bool IsWhiteSpace()
    {
        return IsLineFeed() || string.IsNullOrWhiteSpace(Value);
    }

    public bool IsLetterOrDigit()
    {
        return !IsWhiteSpace();
    }

    public bool IsBlankLineStart(List<CellDiffItem> list)
    {
        foreach (var item in list)
        {
            if (!item.IsWhiteSpace())
            {
                return false;
            }
        }

        if (!list[0].IsLineFeed() || !list[^1].IsLineFeed())
        {
            return false;
        }

        return true;
    }

    public bool IsBlankLineEnd(List<CellDiffItem> list)
    {
        return IsBlankLineStart(list);
    }

    public CellDiffItem DeepCopy() => MemberwiseClone() as CellDiffItem ?? throw new Exception("MemberwiseClone() 失败");

    public bool Equals(CellDiffItem? other)
    {
        if (IsLineFeed() || other?.IsLineFeed() == true)
        {
            return IsLineFeed() && other?.IsLineFeed() == true;
        }

        if (_originCell.Value == null || other?._originCell.Value == null)
        {
            return _originCell.Value == null && other?._originCell.Value == null;
        }
       
        return ExcelCellEquals(_originCell,other._originCell) && _hash == other._hash;
    }

    private bool ExcelCellEquals(ExcelRange cell1,ExcelRange cell2)
    {
        if (!string.IsNullOrWhiteSpace(cell1.Formula) || !string.IsNullOrWhiteSpace(cell2.Formula))
        {
            if (cell1.Formula != cell2.Formula)
            {
                return false;
            }
        }
        else
        {
            if (!cell1.Value.Equals(cell2.Value))
            {
                return false;
            }
        }

        if (cell1.Style.Fill.BackgroundColor.Rgb != cell2.Style.Fill.BackgroundColor.Rgb)
        {
            return false;
        }
        
        return true;
    }

    private int CalculateHashCode()
    {
        var hash = false.GetHashCode();

        // 考虑公式
        if (string.IsNullOrWhiteSpace(_originCell.Formula))
        {
            if (_originCell.Value != null)
            {
                hash = HashCode.Combine(hash,_originCell.Value.GetHashCode());
            }
        }
        else
        {
            hash = HashCode.Combine(hash,_originCell.Formula.GetHashCode());
        }

        if (_originCell.Style.Fill.BackgroundColor.Rgb != null)
        {
            hash = HashCode.Combine(hash,_originCell.Style.Fill.BackgroundColor.Rgb.GetHashCode());
        }
        
        return hash;
    }

    public override int GetHashCode()
    {
        return _hash;
    }

    public override string ToString()
    {
        if (_lineFeed)
        {
            return "[换行]";
        }

        return $"[{Row},{NumberToExcelColName(Col)},{Value}]";
    }

    private string NumberToExcelColName(int col)
    {
        string result = string.Empty;
        if (col > 26)
        {
            result += NumberToExcelColName((col - 1) / 26);
        }
        result += (char)('A' + (col - 1) % 26);
        return result;
    }
}